// es5里面的类  构造函数
// function Person(){
//  this.name ='张三';
//  this.age =12
// }
// 实例化
// let p =new Person()
// console.log(p.name);

// class Common {
//   static myName: string = '静态名称属性'
//   myName: string = '实例名称属性'
//   // 放在=后面的叫值
// }

// class Animal {
//   public readonly name: string
//   constructor(name: string) {
//     this.name = name
//   }
//   // changeName(name: string) {
//   //   this.name = name; //这个ts是报错的
//   // }
// }

// let a9 = new Animal('hello')

// //构造函数和原型链里增加方法
// function Person(){
//   this.name ='小哈';
//   this.age =18
//   this.run =function(){ //实例方法 必须通过new 调用
//     console.log(this.name + '运动');
//   }
// }
// let p =new Person
// console.log(p.run());
// 原型链上的属性会被多个实例共享 构造函数不会
//Person.prototype.sex='男' 原型链上增加属性
// Person.prototype.work =function(){
//   alert(this.name+'在工作')
// }

// 类里面的静态方法
// Person.getInfo =function(){
//   alert('哈哈哈哈哈')
// }
// 调用静态方法
//Person.getInfo()

// es5里的继承
// Web类 继承Person类  原型链+对象冒充的组合继承模式
// function Web(){
//   Person.call(this) //对象冒充实现继承
// }
// let w= new Web()
// w.run()
// w.work() 对象冒充可以继承构造函数里的属性和方法，但是继承不了原型链上的属性和方法
// 原型链实现继承  既可以继承构造函数的属性和方法，又可以继承原型链的属性和方法
// Web.prototype = new Person() //原型链实现继承

// 原型链实现继承的问题
// function Person(name,gae){
//   this.name =name;
//   this.age =age
//   this.run =function (){
//     alert(this.name + '在运动')
//   }
// }
// var p = new Person('张三',20)
// p.run()

// 构造函数实例化子类的时候没法给父类传参

// ts如何创建构造函数
// 1.定义构造函数
// class Person{
//   name:string;  //定义属性  前面省略了public关键字
//   constructor(n:string){  //构造函数  实例化类的时候触发的方法
//     this.name =n
//   }
//   run():void{
//      alert(this.name + '在运动')
//   }
// }
// var p = new Person('张三')
// p.run()

// class Person{
//   name:string;
//   constructor(name:string){
//     this.name =name
//   }
//   getName():string{
//     return this.name
//   }
//   setName(name:string){
//      this.name =name
//   }
// }
// var p =new Person('张三')
// alert(p.getName())  //张三
// p.setName('李四')
// alert(p.getName()) //李四

// 2.ts中实现继承  extends  super
// super 表示调用父类的构造函数
// 当父类和子类都拥有一样的方法时，执行的是子类里的方法
// class Person{
//   name:string;
//   constructor(name:string){
//     this.name =name
//   }
//   run(){
//     alert(`${this.name}在运动`)
//   }
// }

// class Web extends Person{
//   constructor(name:string){
//     super(name)
//   }
//   run(): void {
//     alert(`${this.name}在运动--子类`)
//   }
// }
// var w  =new Web('李四')
// alert(w.run())  //李四在运动--子类i

// 3. 类里面的修饰符  public  protected private
// public  公有  在类里面、子类、类外面都可以访问
// protected 保护类型 在类里面、子类里面可以访问，在类外部不可访问
// private 私有 在类里面可以访问，子类及类外部不可访问

// class Person{
//   name:string;
//   constructor(name:string){
//     this.name = name
//   }
//   public run(){
//     alert(this.name + '在运动')
//   }
//   protected sing(){
//     alert(this.name + '在唱歌')
//   }
//   private drawing(){
//     alert(this.name + '在画画')
//   }
// }
// class Son extends Person{
//     constructor(name:string){
//     super(name)
//   }
//   sing(){
//     alert(this.name + '在唱歌--子类')
//   }
// }
// var s = new Son('小花')

// alert(s.run()) //小花在运动
// alert(s.sing()) // 小花在唱歌--子类
// alert(s.drawing()) //报错

// 4.静态属性 静态方法

// // es5 静态属性
// Person.name ='哈哈哈'
// // es5 静态方法
// Person.run2 =function(){
// console.log('111');
// }
// // 调用
// console.log(Person.name, '222');

// Person.run2()

// class Person{
//   name:string;
//   constructor(name:string){
//     this.name =name
//   }
//   static sing(){
//     alert(this.name + '在唱歌')
//   }
// }
// // 调用静态方法
// Person.sing()

// 5.抽象类  多态
// 多态：父类定义一个方法不去实现，让继承他的子类去实现，
// 每一个子类有不同的表现，多态属于继承的一种

// class Animal{
//   name:string;
//   constructor(name:string){
//     this.name =name
//   }
//   eat(){
//     console.log('吃的方法')
//   }
// }

// class Dog extends Animal{
//   constructor(name:string){
//     super(name)
//   }
//   eat() {
//     return this.name + '啃骨头'
//   }
// }

// let d = new Dog('小狗')
// alert(d.eat()) // 小狗吃骨头

// class Cat extends Animal{
//   constructor(name:string){
//     super(name)
//   }
//   eat() {
//     return this.name + '爱吃鱼'
//   }
// }
// let c = new Dog('小猫')
// alert(c.eat()) // 小猫爱吃鱼

// 抽象方法
// ts中的抽象类：他是提供其他类继承的基类，不能直接被实例化
// 用 abstract 关键字定义抽象类和抽象方法，
// 抽象类中的抽象方法不包含具体实现并且必须在派生类中实现

// abstract class Animal{
//   name:string;
//   constructor(name:string){
//     this.name =name
//   }
//   abstract eat():any

// }

// class Dog extends Animal{
//   constructor(name:string){
//     super(name)
//   }
//   eat(){
//      this.name + '爱吃肉'
//   }
// }

// let d = new Dog('小狗')
// alert(d.eat()) //小狗爱吃肉

// 重写 重载

// 重写
class Animal {
  speak(word: string): string {
    return '动物' + word
  }
}
class Cat extends Animal {
  speak(word: string): string {
    return '猫' + word
  }
}
let cat = new Cat()
console.log(cat.speak('喵喵'))

// 重载
function double(val: number): number
function double(val: string): string
function double(val: any): any {
  if (typeof val == 'number') {
    return val * 2
  }
  return val
}
let r = double(2)
console.log(r) //4
let r1 = double('你好')
console.log(r1) // 你好
